package cn.wolfcode.luowowo.service.impl;

import cn.wolfcode.luowowo.domain.Destination;
import cn.wolfcode.luowowo.domain.Travel;
import cn.wolfcode.luowowo.domain.UserInfo;
import cn.wolfcode.luowowo.query.QueryObject;
import cn.wolfcode.luowowo.query.TravelCondition;
import cn.wolfcode.luowowo.query.TravelQuery;
import cn.wolfcode.luowowo.redis.service.IUserInfoRedisService;
import cn.wolfcode.luowowo.repository.TravelRepository;
import cn.wolfcode.luowowo.service.IDestinationService;
import cn.wolfcode.luowowo.service.ITravelService;
import cn.wolfcode.luowowo.service.IUserInfoService;
import cn.wolfcode.luowowo.util.DBHelper;
import cn.wolfcode.luowowo.util.ParamMap;
import javafx.fxml.LoadException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.List;
import java.util.Optional;

@Service
//@Transactional //事务最后处理
public class TravelServiceImpl implements ITravelService {

    @Autowired
    private TravelRepository repository;

    @Autowired
    private MongoTemplate template;

    @Autowired
    private IUserInfoService userInfoService;

    @Autowired
    private IDestinationService destinationService;

    @Override
    public Page<Travel> query(TravelQuery qo) {
        Query query = new Query();

        //目的地的分页条件
        if (StringUtils.hasLength(qo.getDestId())) {
            query.addCriteria(Criteria.where("destId").is(qo.getDestId()));
        }

        TravelCondition perExpend = qo.getPerExpend();
        TravelCondition day = qo.getDay();
        //人均消费的范围查询
        if (perExpend != null) {
            query.addCriteria(Criteria.where("perExpend").gte(perExpend.getMin()).lte(perExpend.getMax()));
        }
        //旅游天数的范围查询
        if (day != null) {
            query.addCriteria(Criteria.where("day").gte(day.getMin()).lte(day.getMax()));
        }

        // 1：代表默认排序：按时间排序 2：代表按浏览数排序
        if (qo.getOrderType() == 2) {
            qo.setPageable(PageRequest.of(qo.getCurrentPage() - 1, qo.getPageSize(), Sort.Direction.DESC, "viewnum"));
        } else {
            qo.setPageable(PageRequest.of(qo.getCurrentPage() - 1, qo.getPageSize(), Sort.Direction.DESC, "createTime"));
        }


        Page<Travel> page = DBHelper.query(template, Travel.class, query, qo.getPageable());

        //缺少用户对象，前台拿用户的信息报错
        for (Travel travel : page.getContent()) {//编辑分页结果的内容即可
            travel.setAuthor(userInfoService.get(travel.getUserId()));//设置用户信息
        }
        return page;
    }


    @Override
    public void delete(String id) {
        repository.deleteById(id);
    }

    //审核游记
    @Override
    public void changeState(String id, int state) throws LoadException {
        //满足什么条件才进行审核
        //查询游记
        Optional<Travel> optional = repository.findById(id);
        if (!optional.isPresent() && state != Travel.STATE_WAITING) {
            //有内容并且状态是待审核的才审核,否则抛异常
            throw new LoadException("该游记不可符合发布条件！");
        }


        //审核通过做什么，审核通过之后，游记的字段需要更新的字段有：releaseTime  lastUpdateTime  state
        Travel travel = new Travel();
        travel.setId(id);
        travel.setLastUpdateTime(new Date());
        Query query = new Query();
        //惨痛——防止全部更新
        query.addCriteria(Criteria.where("_id").is(id));
        if (state == Travel.STATE_RELEASE) {
            //1待审核
            travel.setState(Travel.STATE_RELEASE);//通过
            travel.setReleaseTime(new Date());//发布时间
        } else {
            //审核拒绝要做什么
            travel.setState(Travel.STATE_REJECT);//拒绝
            travel.setReleaseTime(null);//发布时间
        }
        //更新
        DBHelper.update(template, query, travel,
                "state", "releaseTime", "lastUpdateTime");
    }


    //保存或者修改游记
    @Override
    public String saveOrUpdate(Travel travel) {
        //保存修改操作只能登录后才能操作，需要在表现层验证用户是否登录

        //注意除了前台传过来的数据，还有以下数据真实我们在保存/修改的时候进行维护的
        if (!StringUtils.hasLength(travel.getId())) {
            //添加
            travel.setId(null);
            //添加的时候需要添加创建时间
            travel.setCreateTime(new Date());
            repository.save(travel);
        } else {
            //编辑
            Query query = new Query();
            query.addCriteria(Criteria.where("_id").is(travel.getId()));
            //修改需要维护的字段
            DBHelper.update(template, query, travel,
                    "destId", "destName", "title", "coverUrl",
                    "travelTime", "perExpend", "day", "person",
                    "lastUpdateTime", "isPublic", "state",
                    "summary", "content");
        }

      /*  //缺少用户对象，前台拿用户的信息报错  不在这里做
        UserInfo userInfo = userInfoService.get(travel.getUserId());
        travel.setAuthor(userInfo);*/

        return travel.getId();
    }

    @Override
    public Travel get(String id) {
        Optional<Travel> optional = repository.findById(id);
        if (optional.isPresent()) {
            //将用户信息设置进去
            Travel travel = optional.get();
            travel.setAuthor(userInfoService.get(travel.getUserId()));

            //设置目的地信息
            Destination dest = destinationService.get(travel.getDestId());
            travel.setDest(dest);
            return travel;
        }
        return null; //如果条件不满足就不需要查询了，所以返回null
    }

    //通过目的地id查阅读量前三的游记
    @Override
    public List<Travel> getViewnumTop3(String destId) {
        PageRequest of = PageRequest.of(0, 3, Sort.Direction.DESC, "viewnum");
        return repository.findByDestId(destId, of);
    }

    //查询所有的游记
    @Override
    public List<Travel> list() {
        return repository.findAll();
    }

    //通过目的地的名字查询游记
    @Override
    public List<Travel> findByDestName(String destName) {
        List<Travel> list = repository.findByDestName(destName);
        for (Travel travel : list) {
            //封装数据，
            travel.setAuthor(userInfoService.get(travel.getUserId()));
        }
        return list;
    }
}
